
package edu.hm.devcamp.providers;

import java.util.HashMap;
import java.util.List;

import edu.hm.devcamp.communication.GetService;
import edu.hm.devcamp.presentation.activities.PoiMap;
import edu.hm.devcamp.providers.Pois.categories;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;

/**
 * Wrapper class for the {@link PoiProvider} content provider, so users don't
 * have to deal with SQL
 * 
 * @author Marco
 */

public class PoiProviderRequest {

    private static ChangeListener mListener;

    public static void setListener(ChangeListener newListener) {
        mListener = newListener;
    }

    /**
     * insert a new POI into the database
     * 
     * @param context use "this" as context when calling
     * @param row
     */
    private static Uri insert(Context context, Poi row) {
        ContentValues values = new ContentValues();

        values.put(Pois.POI_ID, row.id);
        values.put(Pois.SOURCE, row.source);
        values.put(Pois.NAME, row.name);
        values.put(Pois.CATEGORY, row.category);
        values.put(Pois.STREET, row.street);
        values.put(Pois.STREETNUM, row.streetnumber);
        values.put(Pois.ZIPCODE, row.zipcode);
        values.put(Pois.CITY, row.city);
        values.put(Pois.COORD_LON, row.longitude);
        values.put(Pois.COORD_LAT, row.latitude);
        values.put(Pois.URL, row.url);
        values.put(Pois.DESC, row.description);
        values.put(Pois.EXTERNAL_ID, row.externalId);
        values.put(Pois.OPENING_TIMES, row.openingTimes);

        Uri loc = Uri.withAppendedPath(Pois.CONTENT_URI, "pois");

        if (PoiMap.LOG_D) {
            Log.d("PoiProviderRequest", "inserting " + row);
        }
        return context.getContentResolver().insert(loc, values);
    }
  
    /**
     * insert a List of {@link PoiWrapperObject}s this method does NOT use the
     * content provider interface as it doesn't support transactions yet.
     * 
     * @param pois
     */
    public static void insertList(Context context, List<Poi> pois) {
        // reset the database
        clean_db(context);

        ContentValues[] valuesArray = new ContentValues[pois.size()];
        int i = 0;
        for (Poi row : pois) {
            ContentValues values = new ContentValues();

            values.put(Pois.POI_ID, row.id);
            values.put(Pois.SOURCE, row.source);
            values.put(Pois.NAME, row.name);
            values.put(Pois.CATEGORY, row.category);
            values.put(Pois.STREET, row.street);
            values.put(Pois.STREETNUM, row.streetnumber);
            values.put(Pois.ZIPCODE, row.zipcode);
            values.put(Pois.CITY, row.city);
            values.put(Pois.COORD_LON, row.longitude);
            values.put(Pois.COORD_LAT, row.latitude);
            values.put(Pois.URL, row.url);
            values.put(Pois.DESC, row.description);
            values.put(Pois.EXTERNAL_ID, row.externalId);
            values.put(Pois.OPENING_TIMES, row.openingTimes);

            valuesArray[i] = values;

            i++;
        }

        PoiProvider.insertLocal(valuesArray);

        if (mListener != null)
            mListener.notifyChange();
    }

    /**
     * clean the database (remove all entries)
     * 
     * @param context
     */
    public static void clean_db(Context context) {
        Log.w("PoiProviderRequest", "Wiping database");
        Uri loc = Uri.withAppendedPath(Pois.CONTENT_URI, "pois");
        context.getContentResolver().delete(loc, null, null);
    }

    /**
     * get a list of all POIs
     * 
     * @param context use "this" as context when calling
     * @return {@link PoiWrapperObject}[] array
     * @throws PoiNoDataException if no results are found
     */
    public static Poi[] getList(Context context) {
        return getList_internal(context, null);
    }

    /**
     * get a list of all POIs matching a specific category
     * 
     * @param context use "this" as context when calling
     * @param category one of the elements in {@link categories}
     * @return {@link PoiWrapperObject}[] array
     * @throws PoiNoDataException if no results are found
     */
    public static Poi[] getList(Context context, categories category) {
        return getList_internal(context, Pois.CATEGORY + "='" + category.toString() + "'");
    }

    /**
     * internal method for getList
     * 
     * @param context the context
     * @param selection if null, no filter, if yes, filter with WHERE
     *            category=selection
     * @return {@link PoiWrapperObject}[] array
     */
    private static Poi[] getList_internal(Context context, String selection) {

        // if anything goes wrong, we return an empty array
        Poi[] ret = new Poi[0];

        // set up the columns we want to fetch
        String[] projection = new String[] {
                Pois.POI_ID, Pois.SOURCE, Pois.CATEGORY, Pois.NAME, Pois.DESC, Pois.STREET,
                Pois.STREETNUM, Pois.ZIPCODE, Pois.CITY, Pois.COORD_LON, Pois.COORD_LAT, Pois.URL,
                Pois.EXTERNAL_ID, Pois.OPENING_TIMES
        };
      
        // set up a cursor, this is the easiest way
        Cursor cursor = PoiProvider.queryLocal(projection, selection, null,
                Pois.POI_ID);

        if (selection == null)
            selection = "";
        if (PoiMap.LOG_D) {
            Log.w("PoiProviderRequest::getList", "Queried for selection: '" + selection + "'");
        }
        if (cursor.moveToFirst()) {
            if (PoiMap.LOG_D) {
                Log.w("ProviderRequest::getList", String.valueOf(cursor.getCount())
                        + " entries for given selection (cat " + selection.toString() + ")");
            }
            ret = new Poi[cursor.getCount()];
            if (cursor.getCount() == 0) {
                cursor.close();
                return null;
            }
            int i = 0;
            do {
                // populate all the fields
                ret[i] = new Poi();
                ret[i].id = cursor.getLong(cursor.getColumnIndex(Pois.POI_ID));
                ret[i].name = cursor.getString(cursor.getColumnIndex(Pois.NAME));
                ret[i].category = cursor.getString(cursor.getColumnIndex(Pois.CATEGORY));
                ret[i].street = cursor.getString(cursor.getColumnIndex(Pois.STREET));
                ret[i].streetnumber = cursor.getString(cursor.getColumnIndex(Pois.STREETNUM));
                ret[i].zipcode = cursor.getString(cursor.getColumnIndex(Pois.ZIPCODE));
                ret[i].city = cursor.getString(cursor.getColumnIndex(Pois.CITY));
                ret[i].longitude = cursor.getFloat(cursor.getColumnIndex(Pois.COORD_LON));
                ret[i].latitude = cursor.getFloat(cursor.getColumnIndex(Pois.COORD_LAT));
                ret[i].url = cursor.getString(cursor.getColumnIndex(Pois.URL));
                ret[i].description = cursor.getString(cursor.getColumnIndex(Pois.DESC));
                ret[i].source = cursor.getString(cursor.getColumnIndex(Pois.SOURCE));
                ret[i].openingTimes = cursor.getString(cursor.getColumnIndex(Pois.OPENING_TIMES));
                ret[i].externalId = cursor.getString(cursor.getColumnIndex(Pois.EXTERNAL_ID));

                i++;
            } while (cursor.moveToNext());
        } else {
            cursor.close();
            ret = null;
        }

        cursor.close();
        return ret;
    }
}
